import React, { useEffect, useRef, useState } from 'react';
import { GestureRecognizer, FilesetResolver, DrawingUtils } from '@mediapipe/tasks-vision';
import { Toast } from 'antd-mobile';

interface GestureInfo {
    categoryName: string;
    categoryScore: string;
    handedness: string;
}

// 手势枚举
const enumGesture: { [key: string]: string } = {
    Closed_Fist: '握紧拳头',
    Open_Palm: '张开手掌',
    Thumb_Up: '竖起大拇指',
    Thumb_Down: '拇指朝下',
    Pointing_Up: '指向上',
    Pointing_Down: '指向下',
    Victory: '剪刀',
    None: '未识别',
};

const GestureRecognizerComponent: React.FC = () => {
    const videoRef = useRef<HTMLVideoElement>(null);
    const canvasRef = useRef<HTMLCanvasElement>(null);
    const gestureRecognizerRef = useRef<GestureRecognizer | null>(null);
    const [runningMode, setRunningMode] = useState<string | null>(null);
    const [videoGestureInfo, setVideoGestureInfo] = useState<GestureInfo>({
        categoryName: '',
        categoryScore: '',
        handedness: '',
    });
    // 用于防抖：避免同一手势连续触发多次
    const lastTriggerTime = useRef<number>(0);
    const DEBOUNCE_DELAY = 1000; // 防抖间隔（毫秒）：1秒内同一手势只触发一次


    // --------------------------
    // 1. 定义手势对应的事件处理函数
    // --------------------------
    // 示例1：“竖起大拇指”触发提交操作
    const handleThumbUp = () => {
        console.log('触发【提交】操作');
        Toast.show({ icon: 'success', content: '检测到“竖起大拇指”，执行提交！' });
    };

    // 示例2：“剪刀”触发重置操作
    const handleVictory = () => {
        console.log('触发【重置】操作');
        Toast.show({ icon: 'info', content: '检测到“剪刀手势”，执行重置！' });
    };

    // 示例3：“握紧拳头”触发关闭操作
    const handleClosedFist = () => {
        console.log('触发【关闭】操作');
        Toast.show({ icon: 'fail', content: '检测到“握紧拳头”，执行关闭！' });
    };

    // 修复：“指向上”触发页面滚动到上一屏
    const handlePointingUp = () => {
        console.log('触发【向上翻页】操作');
        Toast.show({ icon: 'fail', content: '检测到“向上翻页”，向上翻页！' });

        // 获取当前视口高度
        const screenHeight = window.innerHeight;
        // 获取当前滚动位置
        const currentScrollY = window.scrollY;
        // 计算目标位置：当前位置减去一屏高度（向上滚动）
        // 使用Math.max确保不会滚动到负位置（页面顶部）
        const targetScrollY = Math.max(0, currentScrollY - screenHeight);

        // 平滑滚动到目标位置
        window.scrollTo({
            top: targetScrollY,
            behavior: 'smooth' // 平滑动画
        });
    };

    // 新增：“指向下”触发页面滚动到下一屏（可选）
    const handlePointingDown = () => {
        console.log('触发【向下翻页】操作');

        const screenHeight = window.innerHeight;
        const currentScrollY = window.scrollY;
        // 计算文档总高度
        const documentHeight = document.documentElement.scrollHeight;
        // 计算目标位置：当前位置加上一屏高度（向下滚动）
        // 使用Math.min确保不会滚动超出页面底部
        const targetScrollY = Math.min(
            currentScrollY + screenHeight,
            documentHeight - screenHeight
        );

        window.scrollTo({
            top: targetScrollY,
            behavior: 'smooth'
        });
    };

    // --------------------------
    // 2. 监听手势变化，触发对应事件
    // --------------------------
    useEffect(() => {
        // 仅当识别到有效手势且置信度≥80%时触发（可调整阈值）
        const confidenceThreshold = 80; // 置信度阈值（%）
        const currentScore = parseFloat(videoGestureInfo.categoryScore);
        const currentGesture = videoGestureInfo.categoryName;

        if (currentGesture && currentScore >= confidenceThreshold) {
            // 防抖处理：避免短时间内重复触发
            const now = Date.now();
            if (now - lastTriggerTime.current < DEBOUNCE_DELAY) {
                return;
            }
            lastTriggerTime.current = now;

            // 根据手势触发对应事件
            switch (currentGesture) {
                case enumGesture.Thumb_Up:
                    handleThumbUp();
                    break;
                case enumGesture.Victory:
                    handleVictory();
                    break;
                case enumGesture.Closed_Fist:
                    handleClosedFist();
                    break;
                case enumGesture.Pointing_Up:
                    handlePointingUp();
                    break;
                case enumGesture.Pointing_Down:
                    handlePointingDown();
                    break;
                default:
                    break;
            }
        }
    }, [videoGestureInfo]); // 监听手势信息变化



    // 判断是否可以使用摄像头
    const hasGetUserMedia = () => !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia);

    // 创建手势识别器
    const createGestureRecognizer = async () => {
        try {
            // 加载MediaPipe WASM模块
            const vision = await FilesetResolver.forVisionTasks(
                'https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.3/wasm'
            );

            // 创建手势识别器实例
            gestureRecognizerRef.current = await GestureRecognizer.createFromOptions(vision, {
                baseOptions: {
                    modelAssetPath: '/gesture_recognizer.task', // 确保模型在public目录
                    delegate: 'GPU',
                },
                numHands: 2,
            });

            console.log('手势识别器加载完毕');
            predictWebcam();
        } catch (error) {
            console.error('加载手势识别器时出错:', error);
            Toast.show({ icon: 'fail', content: '加载手势识别器失败，请检查网络连接或模型路径' });
        }
    };

    // 识别视频中的手势
    const predictWebcam = async () => {
        if (!hasGetUserMedia()) return Toast.show({ icon: 'fail', content: '此设备不允许使用摄像头!' });

        const video = videoRef.current;
        const canvasElement = canvasRef.current;

        if (!video || !canvasElement || !gestureRecognizerRef.current) {
            return Toast.show({ icon: 'fail', content: '视频或画布元素未正确初始化' });
        }

        // 设置识别模式为视频
        if (runningMode !== 'VIDEO') {
            setRunningMode('VIDEO');
            await gestureRecognizerRef.current.setOptions({ runningMode: 'VIDEO' });
        }
        await gestureRecognizerRef.current.setOptions({ numHands: 2 });

        // 同步Canvas尺寸与视频尺寸
        canvasElement.width = video.clientWidth;
        canvasElement.height = video.clientHeight;
        const canvasCtx = canvasElement.getContext('2d');
        if (!canvasCtx) return;

        let lastVideoTime = -1;

        // 处理视频帧的核心函数
        const processVideoFrame = () => {
            if (!video || !gestureRecognizerRef.current) return;

            // 只在视频时间变化时识别（优化性能）
            const nowInMs = Date.now();
            let results: any = {};
            if (video.currentTime !== lastVideoTime) {
                lastVideoTime = video.currentTime;
                results = gestureRecognizerRef.current.recognizeForVideo(video, nowInMs);
            }

            // 清除画布并准备绘制（关键：这里添加镜像处理）
            canvasCtx.save();
            canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);

            // 水平镜像翻转Canvas（让显示符合用户视觉习惯）
            canvasCtx.scale(-1, 1); // 水平翻转
            canvasCtx.translate(-canvasElement.width, 0); // 平移修正位置

            // 绘制手势关键点和连接线
            const drawingUtils = new DrawingUtils(canvasCtx);
            if (results.landmarks) {
                for (const landmarks of results.landmarks) {
                    // 绘制连接线
                    drawingUtils.drawConnectors(landmarks, GestureRecognizer.HAND_CONNECTIONS, {
                        color: '#00FF00',
                        lineWidth: 3,
                    });
                    // 绘制关节点
                    drawingUtils.drawLandmarks(landmarks, {
                        color: '#FF0000',
                        radius: 2.5,
                    });
                }
            }

            canvasCtx.restore(); // 恢复Canvas状态

            // 处理识别结果（关键：修正左右手标识）
            if (results?.gestures?.length > 0) {
                // 因为Canvas做了镜像，所以识别的"左"实际显示为"右"，需要反转
                const originalHandedness = results.handednesses[0][0].displayName;
                const correctedHandedness = originalHandedness === 'Left' ? 'Right' : 'Left';

                setVideoGestureInfo({
                    categoryName: enumGesture[results.gestures[0][0].categoryName] || '未知手势',
                    categoryScore: (results.gestures[0][0].score * 100).toFixed(2),
                    handedness: correctedHandedness, // 使用修正后的左右手
                });
            } else {
                setVideoGestureInfo({
                    categoryName: '',
                    categoryScore: '',
                    handedness: '',
                });
            }

            // 持续处理下一帧
            requestAnimationFrame(processVideoFrame);
        };

        // 启动摄像头
        navigator.mediaDevices.getUserMedia({ 
            video: { 
                width: { ideal: 480 },  // 降低分辨率提高性能
                height: { ideal: 360 } 
            } 
        })
            .then(stream => {
                if (video) {
                    video.srcObject = stream;
                    video.addEventListener('loadeddata', processVideoFrame); // 视频加载完成后开始处理
                }
            })
            .catch(err => {
                console.error("访问摄像头时出错:", err);
                Toast.show({ icon: 'fail', content: '访问摄像头失败，请检查权限设置' });
            });
    };

    // 组件挂载时初始化识别器
    useEffect(() => {
        createGestureRecognizer();

        // 组件卸载时清理资源
        return () => {
            if (gestureRecognizerRef.current) {
                gestureRecognizerRef.current.close();
            }
            const video = videoRef.current;
            if (video && video.srcObject) {
                (video.srcObject as MediaStream).getTracks().forEach(track => track.stop());
                video.srcObject = null;
            }
        };
    }, []);

    return (
        <div className="gesture-recognition-container">
            <div className="video-container" style={{ position: 'relative' }}>
                {/* 视频隐藏（opacity:0保持元素存在但不可见，确保尺寸正确） */}
                <video
                    ref={videoRef}
                    width="640"
                    height="480"
                    autoPlay
                    muted
                    playsInline
                    style={{ opacity: 0, position: 'absolute' }} // 绝对定位避免影响布局
                />
                {/* 只显示Canvas（镜像后的画面） */}
                <canvas
                    ref={canvasRef}
                    width="640"
                    height="480"
                    style={{ border: '1px solid #000' }} // 可选：添加边框方便查看
                />
            </div>

            {/* 显示识别结果 */}
            {videoGestureInfo.categoryName && (
                <div className="gesture-info" style={{ marginTop: 10 }}>
                    <div>识别手势: {videoGestureInfo.categoryName}</div>
                    <div>置信度: {videoGestureInfo.categoryScore}%</div>
                    <div>手: {videoGestureInfo.handedness}</div>
                </div>
            )}
        </div>
    );
};

export default GestureRecognizerComponent;